package com.ala4.oxcafe.utils;

import com.ala4.oxcafe.common.utils.RedisUtil;
import com.ala4.oxcafe.common.utils.date.DateUtil;
import jakarta.validation.constraints.NotNull;

/**
 * 单号生成工具类
 *
 * @author capable
 * @since 2025-04-11 15:18
 */
public class CodeGenUtil {

    public static final String CODE_GENERATOR = "code:generator:";
    private static final String DATE_FORMAT = "yyyyMMdd";
    private static final String DATE_FORMAT_HH = "yyyyMMddHH";
    private static final String DATETIME_FORMAT = "yyyyMMddHHmmss";
    private static final String SHORT_DATE_FORMAT = "yyMMdd";
    /**
     * 默认长度
     */
    private static final int NUMBER_LENGTH = 4;

    /**
     * 默认过期时间 一天
     */
    private static final int DEFAULT_EXPIRE_SECONDS = 3600 * 24;

    /**
     * 根据指定前缀序列生成 prefix + yyyyMMdd + 四位数
     *
     * @param prefix 前缀
     * @return
     */
    public static String getDateFormatCode(String prefix) {
        return prefix + generateCode(prefix, DATE_FORMAT, NUMBER_LENGTH);
    }

    public static String getDateFormatHHCode(String prefix) {
        return prefix + generateCode(prefix, DATE_FORMAT_HH, NUMBER_LENGTH);
    }

    /**
     * 根据指定前缀和长度序列生成 prefix + yyyyMMdd + 给定长度数字
     *
     * @param prefix 前缀
     * @param length 后续数字长度
     * @return
     */
    public static String getDateFormatCode(String prefix, int length) {
        return prefix + generateCode(prefix, DATE_FORMAT, length);
    }

    /**
     * 根据指定前缀序列生成 prefix + yyyyMMddHHmmss + 四位数
     *
     * @param prefix 前缀
     * @return
     */
    public static String getDateTimeFormatCode(String prefix) {
        return prefix + generateCode(prefix, DATETIME_FORMAT, NUMBER_LENGTH);
    }

    /**
     * 根据指定前缀和长度序列生成 prefix + yyyyMMddHHmmss + 给定长度数字
     *
     * @param prefix 前缀
     * @param length 后续数字长度
     * @return
     */
    public static String getDateTimeFormatCode(String prefix, int length) {
        return prefix + generateCode(prefix, DATETIME_FORMAT, length);
    }

    /**
     * 根据指定前缀序列生成 prefix + yyMMdd + 四位数
     *
     * @param prefix 前缀
     * @return
     */
    public static String getShortDateFormatCode(String prefix) {
        return prefix + generateCode(prefix, SHORT_DATE_FORMAT, NUMBER_LENGTH);
    }

    /**
     * 根据指定前缀序列生成 prefix + yyMMdd + 四位数
     *
     * @param prefix 前缀
     * @return
     */
    public static String getShortDateFormatCode(String prefix, int length) {
        return prefix + generateCode(prefix, SHORT_DATE_FORMAT, length);
    }


    @NotNull
    private static String generateCode(String key, String format, int length) {
        String time = DateUtil.nowDateString(format);
        key = CODE_GENERATOR + key + time;
        // 直接调用 INCR
        Long count = RedisUtil.incr(key);

        // 首次自增时设置过期时间
        if (count == 1) {
            RedisUtil.expire(key, DEFAULT_EXPIRE_SECONDS);
        }
        return time + formate(count.toString(), length);
    }

    /**
     * 按照给定的长度格式化数字，不足位在前面补零
     *
     * @param value
     * @param length 长度，如果给定的长度小于value的长度，则默认使用value的长度
     * @return
     */
    private static String formate(String value, int length) {
        if (value.length() > length) {
            length = value.length();
        }
        return String.format("%" + length + "d", Long.parseLong(value)).replace(" ", "0");
    }

}
